package com.chlp.core.framework.filter;

import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.defaults.DefaultSqlSession;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import java.lang.reflect.InvocationTargetException;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Properties;

/**
 * 给各实体对象在增加、修改时，自动添加操作属性信息。
 *
 * @author ChenLiPeng
 */
@ConditionalOnProperty(name = "cafe.enable.mybatis.filed.fill", havingValue = "true")
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
@Component
public class MybatisAutoFillInterceptor implements Interceptor {

	private Logger logger = LogManager.getLogger(MybatisAutoFillInterceptor.class);

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		logger.info("----------> mybatis拦截器，实现新增、修改时公共字段自动填充 <----------");
		Object[] args = invocation.getArgs();
		// 设置公共属性
		Object object = args[1];
		if (object != null) {
			MappedStatement mappedStatement = (MappedStatement) args[0];
			//获得方法类型
			SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
			// 插入或更新多条数据时
			if (object instanceof DefaultSqlSession.StrictMap) {
				DefaultSqlSession.StrictMap map = (DefaultSqlSession.StrictMap) object;
				if (map.containsKey("collection")) {
					List<Object> objectList = (List<Object>) map.get("collection");
					for (Object obj : objectList) {
						setProperty(sqlCommandType, obj);
					}
				}
			} else {
				setProperty(sqlCommandType, object);
			}
		}
		return invocation.proceed();
	}

	private void setProperty(SqlCommandType sqlCommandType, Object object) {
		//新增
		if (sqlCommandType == SqlCommandType.INSERT) {
			setInsertProperty(object);
		} else if (sqlCommandType == SqlCommandType.UPDATE) {
			//修改
			setUpdateProperty(object);
		}
	}

	/**
	 * 设置更新时公共属性
	 */
	private void setUpdateProperty(Object obj) {
		try {
			BeanMap map = new BeanMap(obj);
			setUpdate(obj, map);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 设置新增时公共属性
	 */
	private void setInsertProperty(Object obj) {
		try {
			BeanMap map = new BeanMap(obj);

			String createUser = "createUser";
			if (map.containsKey(createUser)) {
				String createUser1 = BeanUtils.getProperty(obj, createUser);
				if (createUser1 == null) {
					BeanUtils.setProperty(obj, createUser, createUser);
				}
			}

			String createTime = "createTime";
			if (map.containsKey(createTime)) {
				String createTime1 = BeanUtils.getProperty(obj, createTime);
				if (createTime1 == null) {
					try {
						BeanUtils.setProperty(obj, createTime, new Date());
					} catch (Exception e) {
						BeanUtils.setProperty(obj, createTime, LocalDateTime.now());
					}
				}
			}

			String markStatus = "markStatus";
			if (map.containsKey(markStatus)) {
				String markStatus1 = BeanUtils.getProperty(obj, markStatus);
				if (markStatus1 == null) {
					BeanUtils.setProperty(obj, markStatus, 0);
				}
			}

			String companyCode = "companyCode";
			if (map.containsKey(companyCode)) {
				String companyCode1 = BeanUtils.getProperty(obj, companyCode);
				if (companyCode1 == null) {
					String company = "";
					BeanUtils.setProperty(obj, companyCode, company);
				}
			}

			setUpdate(obj, map);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void setUpdate(Object obj, BeanMap map) throws IllegalAccessException, InvocationTargetException,
			NoSuchMethodException {
		String lastUpdateTime = "lastUpdateTime";
		if (map.containsKey(lastUpdateTime)) {
			String lastUpdateTime1 = BeanUtils.getProperty(obj, lastUpdateTime);
			if (lastUpdateTime1 == null) {
				try {
					BeanUtils.setProperty(obj, lastUpdateTime, new Date());
				} catch (Exception e) {
					BeanUtils.setProperty(obj, lastUpdateTime, LocalDateTime.now());
				}
			}
		}

		String lastUpdateUser = "lastUpdateUser";
		if (map.containsKey(lastUpdateUser)) {
			String lastUpdateUser1 = BeanUtils.getProperty(obj, lastUpdateUser);
			if (lastUpdateUser1 == null) {
				String createUser = "";
				BeanUtils.setProperty(obj, lastUpdateUser, createUser);
			}
		}
	}

	@Override
	public Object plugin(Object o) {
		return Plugin.wrap(o, this);
	}

	@Override
	public void setProperties(Properties properties) {
		// 无要设置的属性
	}
}
